🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / core / service / src / androidMain / kotlin / org / meshtastic / core / service / ReplyReceiver.kt
Displaying Raw • Download
core/service/src/androidMain/kotlin/org/meshtastic/core/service/ReplyReceiver.kt 33fbb9f7fcab4786c6db51e1773fc1d396de0cf3 (33fbb9f7) Text, 4.38 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.service
Tff7b72import T7ee787android.content.BroadcastReceiver
Tff7b72import T7ee787android.content.Context
Tff7b72import T7ee787android.content.Intent
Tff7b72import T7ee787androidx.core.app.RemoteInput
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787kotlinx.coroutines.CoroutineScope
Tff7b72import T7ee787kotlinx.coroutines.SupervisorJob
Tff7b72import T7ee787kotlinx.coroutines.launch
Tff7b72import T7ee787org.koin.core.component.KoinComponent
Tff7b72import T7ee787org.koin.core.component.inject
Tff7b72import T7ee787org.meshtastic.core.common.util.nowMillis
Tff7b72import T7ee787org.meshtastic.core.di.CoroutineDispatchers
Tff7b72import T7ee787org.meshtastic.core.model.ContactKey
Tff7b72import T7ee787org.meshtastic.core.model.DataPacket
Tff7b72import T7ee787org.meshtastic.core.repository.MeshNotificationManager
Tff7b72import T7ee787org.meshtastic.core.repository.PacketRepository
Tff7b72import T7ee787org.meshtastic.core.repository.RadioController
T8b949e/**
* A [BroadcastReceiver] that handles inline replies from notifications.
*
* This receiver is triggered when a user replies to a message directly from a notification. It extracts the reply text
* and the contact key from the intent, sends the message using the [ServiceRepository], and then cancels the original
* notification.
*/
Tff7b72class T56d364ReplyReceiver Tb4b4b4:
Te6edf3BroadcastReceiverTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3KoinComponent Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3radioControllerTb4b4b4: Te6edf3RadioController Tff7b72by Te6edf3injectTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3meshServiceNotificationsTb4b4b4: Te6edf3MeshNotificationManager Tff7b72by Te6edf3injectTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3packetRepositoryTb4b4b4: Te6edf3PacketRepository Tff7b72by Te6edf3injectTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3dispatchersTb4b4b4: Te6edf3CoroutineDispatchers Tff7b72by Te6edf3injectTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3scope Tff7b72by Te6edf3lazy Tb4b4b4{ Te6edf3CoroutineScopeTb4b4b4(Te6edf3dispatchersTb4b4b4.Te6edf3io Tff7b72+ Te6edf3SupervisorJobTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}
Tff7b72companion Tff7b72object Tb4b4b4{
Tff7b72private Tff7b72const Tff7b72val Te6edf3TAG Tff7b72= Ta5d6ff"Ta5d6ffReplyReceiverTa5d6ff"
Tff7b72const Tff7b72val Te6edf3REPLY_ACTION Tff7b72= Ta5d6ff"Ta5d6fforg.meshtastic.app.REPLY_ACTIONTa5d6ff"
Tff7b72const Tff7b72val Te6edf3CONTACT_KEY Tff7b72= Ta5d6ff"Ta5d6ffcontactKeyTa5d6ff"
Tff7b72const Tff7b72val Te6edf3KEY_TEXT_REPLY Tff7b72= Ta5d6ff"Ta5d6ffkey_text_replyTa5d6ff"
Tb4b4b4}
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooGenericExceptionCaughtTa5d6ff"Tb4b4b4) T8b949e// a reply must never crash the receiver, whatever the radio throws
Tff7b72override Tff7b72fun Td2a8ffonReceiveTb4b4b4(Te6edf3contextTb4b4b4: Te6edf3ContextTb4b4b4, Te6edf3intentTb4b4b4: Te6edf3IntentTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3remoteInput Tff7b72= Te6edf3RemoteInputTb4b4b4.Te6edf3getResultsFromIntentTb4b4b4(Te6edf3intentTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3remoteInput Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3wTb4b4b4(Te6edf3tag Tff7b72= Te6edf3TAGTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffreply received but RemoteInput was nullTa5d6ff" Tb4b4b4}
Tff7b72return
Tb4b4b4}
Tff7b72val Te6edf3contactKey Tff7b72= Te6edf3intentTb4b4b4.Te6edf3getStringExtraTb4b4b4(Te6edf3CONTACT_KEYTb4b4b4)Tb4b4b4.Te6edf3orEmptyTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3message Tff7b72= Te6edf3remoteInputTb4b4b4.Te6edf3getCharSequenceTb4b4b4(Te6edf3KEY_TEXT_REPLYTb4b4b4)Tff7b72?.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3orEmptyTb4b4b4(Tb4b4b4)
Te6edf3LoggerTb4b4b4.Te6edf3iTb4b4b4(Te6edf3tag Tff7b72= Te6edf3TAGTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffreply for contactKey=Tffd700$Te6edf3contactKeyTa5d6ff len=Tffd700${Te6edf3messageTb4b4b4.Te6edf3lengthTffd700}Ta5d6ff" Tb4b4b4}
Tff7b72val Te6edf3pendingResult Tff7b72= Te6edf3goAsyncTb4b4b4(Tb4b4b4)
Te6edf3scopeTb4b4b4.Te6edf3launch Tb4b4b4{
Tff7b72try Tb4b4b4{
T8b949e// Send first so the reply isn't lost; then dismiss. The cancel can't break the send.
Te6edf3sendMessageTb4b4b4(Te6edf3messageTb4b4b4, Te6edf3contactKeyTb4b4b4)
T8b949e// Replying implies the conversation has been read — mark it so, like the mark-as-read action.
T8b949e// Android Auto keys notification dismissal off read state, not just cancel().
Te6edf3packetRepositoryTb4b4b4.Te6edf3clearUnreadCountTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3nowMillisTb4b4b4)
Te6edf3LoggerTb4b4b4.Te6edf3iTb4b4b4(Te6edf3tag Tff7b72= Te6edf3TAGTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffreply sent + marked readTa5d6ff" Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3tag Tff7b72= Te6edf3TAGTb4b4b4, Te6edf3throwable Tff7b72= Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffreply send failedTa5d6ff" Tb4b4b4}
Tb4b4b4} Tff7b72finally Tb4b4b4{
Te6edf3runCatching Tb4b4b4{ Te6edf3meshServiceNotificationsTb4b4b4.Te6edf3cancelMessageNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3onFailure Tb4b4b4{ Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3tag Tff7b72= Te6edf3TAGTb4b4b4, Te6edf3throwable Tff7b72= Tffa657itTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffcancel notification failedTa5d6ff" Tb4b4b4} Tb4b4b4}
Te6edf3pendingResultTb4b4b4.Te6edf3finishTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffsendMessageTb4b4b4(Te6edf3strTb4b4b4: Tffa657StringTb4b4b4, Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
T8b949e// contactKey: unique contact key filter (channel)+(nodeId)
Tff7b72val Te6edf3parsedKey Tff7b72= Te6edf3ContactKeyTb4b4b4(Te6edf3contactKeyTb4b4b4)
Tff7b72val Te6edf3p Tff7b72= Te6edf3DataPacketTb4b4b4(Te6edf3parsedKeyTb4b4b4.Te6edf3addressStringTb4b4b4, Te6edf3parsedKeyTb4b4b4.Te6edf3channelTb4b4b4, Te6edf3strTb4b4b4)
Te6edf3radioControllerTb4b4b4.Te6edf3sendMessageTb4b4b4(Te6edf3pTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.2 - Generated in 0.03s